]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
screencastService: Set PipelineState to PLAYING on actual state-change
authorJonas Dreßler <verdre@v0yd.nl>
Thu, 3 Feb 2022 10:26:59 +0000 (11:26 +0100)
committerJonas Dreßler <verdre@v0yd.nl>
Tue, 25 Apr 2023 16:57:51 +0000 (18:57 +0200)
Right now when we tell gstreamer to move the pipeline to the state
PLAYING, we pretend that happens immediately and set our PipelineState
to PLAYING right afterwards.

In reality though it's more complicated than that: Gstreamer changes
states asynchronously and set_state() returns a Gst.StateChangeReturn.ASYNC.
In that case we should wait until the according STATE_CHANGED event happens
on the bus, and only then set our PipelineState to PLAYING.

Since the STATE_CHANGED event will also happen when set_state() returns
SUCCESS, we can use the same async logic for that.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>

js/dbusServices/screencast/screencastService.js

index 497b7d2063bcf07c1b17eb0faa67f9f2d22449cf..32af1e320fddfafb43680dc05bed4d9e081859d8 100644 (file)
@@ -183,11 +183,14 @@ var Recorder = class {
         const bus = this._pipeline.get_bus();
         bus.add_watch(bus, this._onBusMessage.bind(this));
 
-        this._pipeline.set_state(Gst.State.PLAYING);
-        this._pipelineState = PipelineState.PLAYING;
+        const retval = this._pipeline.set_state(Gst.State.PLAYING);
 
-        this._startRequest.resolve();
-        delete this._startRequest;
+        if (retval === Gst.StateChangeReturn.SUCCESS ||
+            retval === Gst.StateChangeReturn.ASYNC) {
+            // We'll wait for the state change message to PLAYING on the bus
+        } else {
+            this._handleFatalPipelineError('Failed to start pipeline');
+        }
     }
 
     startRecording() {
@@ -230,6 +233,21 @@ var Recorder = class {
 
     _onBusMessage(bus, message, _) {
         switch (message.type) {
+        case Gst.MessageType.STATE_CHANGED: {
+            const [, newState] = message.parse_state_changed();
+
+            if (this._pipelineState === PipelineState.INIT &&
+                message.src === this._pipeline &&
+                newState === Gst.State.PLAYING) {
+                this._pipelineState = PipelineState.PLAYING;
+
+                this._startRequest.resolve();
+                delete this._startRequest;
+            }
+
+            break;
+        }
+
         case Gst.MessageType.EOS:
             switch (this._pipelineState) {
             case PipelineState.STOPPED: